package org.bjf.modules.sys.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.bjf.cache.CacheNameConfig;
import org.bjf.modules.core.service.BaseService;
import org.bjf.modules.sys.bean.SysMenu;
import org.bjf.modules.sys.bean.SysRoleMenu;
import org.bjf.modules.sys.bean.SysUserRole;
import org.bjf.modules.sys.mapper.SysRoleMenuMapper;
import org.bjf.modules.sys.query.SysRoleMenuQuery;
import org.bjf.modules.sys.query.SysUserRoleQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author bjf
 * @date 2017/11/27
 */
@Service
@Slf4j
public class SysRoleMenuService extends BaseService<SysRoleMenuMapper, SysRoleMenu, SysRoleMenuQuery> {

    @Autowired
    private SysMenuService menuService;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private SysUserRoleService userRoleService;

    @Override
    protected LambdaQueryWrapper<SysRoleMenu> buildQuery(SysRoleMenuQuery q) {
        if (q == null) {
            return null;
        }
        LambdaQueryWrapper<SysRoleMenu> qw = new LambdaQueryWrapper<>();
        qw.eq(q.getSysMenuId() != null, SysRoleMenu::getSysMenuId, q.getSysMenuId());
        qw.eq(q.getSysRoleId() != null, SysRoleMenu::getSysRoleId, q.getSysRoleId());
        qw.in(!CollectionUtils.isEmpty(q.getRoleIdList()), SysRoleMenu::getSysRoleId, q.getRoleIdList());
        return qw;
    }


    /**
     * 给角色分配菜单
     */
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = CacheNameConfig.RedisCacheEnum.Names.SYS, key = "'live:rolemenu:listMenu:' + #roleId")
    public void updateMenu(Long roleId, String menuIds) {
        //===1.先删除角色的菜单
        LambdaQueryWrapper<SysRoleMenu> qw = new LambdaQueryWrapper<>();
        qw.eq(SysRoleMenu::getSysRoleId, roleId);
        this.delete(qw);

        //===2.新增角色菜单
        String[] arr = StringUtils.split(menuIds, ",");
        if (arr.length > 0) {


            List<Long> menuIdList = Arrays.stream(arr).map(Long::parseLong).collect(Collectors.toList());
            List<SysMenu> menus = menuService.listByIds(menuIdList);

            List<SysRoleMenu> list = Lists.newArrayList();
            for (SysMenu menu : menus) {
                SysRoleMenu rm = new SysRoleMenu().setSysRoleId(roleId).setSysMenuId(menu.getId()).setSysAppId(menu.getSysAppId());
                list.add(rm);
            }
            this.addBatch(list);
        }

        //===3.清除用户菜单缓存
        sysUserService.clearUserCache();
    }

    /**
     * 查询用户的菜单
     */
    @Cacheable(value = CacheNameConfig.RedisCacheEnum.Names.SYS, key = "'live:menu:listByUser:' + #sysUserId")
    public List<SysMenu> listByUser(long sysUserId) {
        //===1.取用户所有角色
        SysUserRoleQuery urQuery = new SysUserRoleQuery()
                .setSysUserId(sysUserId);
        List<SysUserRole> userRoles = userRoleService.listAll(urQuery);

        //===2.查询所有角色的菜单
        return listMenu(
                userRoles.stream().map(SysUserRole::getSysRoleId).collect(Collectors.toList()));
    }

    /**
     * 查询角色菜单
     */
    public List<SysMenu> listMenu(List<Long> roleIdList) {
        List<SysMenu> all = new ArrayList<>();
        for (Long roleId : roleIdList) {
            all.addAll(listMenu(roleId));
        }
        return all;

    }

    /**
     * 查询角色菜单
     */
    @Cacheable(value = CacheNameConfig.RedisCacheEnum.Names.SYS, key = "'live:rolemenu:listMenu:' + #roleId")
    public List<SysMenu> listMenu(Long roleId) {
        //===1.根据角色查acl菜单
        SysRoleMenuQuery aclQuery = new SysRoleMenuQuery()
                .setSysRoleId(roleId);
        List<SysRoleMenu> roleMenus = this.listAll(aclQuery);
        Set<Long> menuIdList = roleMenus.stream().map(SysRoleMenu::getSysMenuId).collect(Collectors.toSet());
        //===2.查询菜单
        return menuService.listByIds(menuIdList);
    }

}
